#include "json.h"
#include <stdio.h>
#include <assert.h>
#include <iostream>

using namespace Json;
using namespace std;

namespace Json
{
	//定义空的各个json值
	struct Init
	{
		json::array 	empty_array;
		json::object 	empty_object;
		json 			empty_json;
		double 			empty_double=0.0;
		int 			empty_int=0;
		bool 			empty_bool=false;
		string 			empty_string;
	};


	Init &Empty()
	{
		static Init init;
		return init;
	}

	void print(const double &d,string &out)
	{
		char buf[32]={0};
		sprintf(buf,"%0.8lf",d);
		out+=buf;
	}

	void print(const int &i,string &out)
	{
		char buf[32]={0};
		sprintf(buf,"%d",i);
		out+=buf;
	}

	void print(const string &str,string &out)
	{
		out+="\""+str+"\"";
	}

	void print(const json::array &arr,string &out)
	{
		int count=0;
		out+="[";
		for(const auto &it:arr)
		{
			if(count++>0)out+=",";
			it.print(out);
		}
		out+="]";
	}

	void print(const json::object &obj,string &out)
	{
		int count=0;
		out+="{";
		for(const auto &it:obj)
		{
			if(count++>0)out+=",";
			out+="\""+it.first+"\":";
			it.second.print(out);
		}
		out+="}";
	}

	class json_value
	{
		friend class json;
	protected:
		virtual json::Type type()=0;
		virtual void print(string &out)=0;
		virtual json &operator[](const string &sz){return Empty().empty_json;}
		virtual json &operator[](int sz)		{return Empty().empty_json;}
		virtual int 			&get_int()		{return Empty().empty_int;}
		virtual double 		&get_double()	{return Empty().empty_double;}
		virtual string 			&get_str()		{return Empty().empty_string;}
		virtual json::array		&get_array()	{return Empty().empty_array;}
		virtual json::object	&get_object()	{return Empty().empty_object;}

	};

	template<json::Type t,typename T>
	class value:public json_value
	{
	protected:
		explicit value(const T &m_val):m_value(m_val){}
		explicit value(T &&m_val):m_value(move(m_val)){}

		json::Type type(){return t;}
		void print(string &out){Json::print(m_value,out);}

	protected:
		T m_value;
	};

	class json_double:public value<json::Double,double>
	{
		double &get_double()	{return m_value;}
	public:
		json_double(const double &d):value(d){}
	};

	class json_int:public value<json::Int,int>
	{
		int &get_int()	{return m_value;}
	public:
		json_int(const int &d):value(d){}
	};


	class json_string:public value<json::String,string>
	{
		string &get_string()	{return m_value;}
	public:
		json_string(const string &str)		:value(str){}
		json_string(string &&str)			:value(move(str)){}
	};


	class json_array:public value<json::Array,json::array>
	{
		json::array &get_array()	{return m_value;}
		json &operator[](int sz){return m_value[sz];}
	public:
		json_array(const json::array &arr)	:value(arr){}
		json_array(json::array &&arr)		:value(move(arr)){}

	};

	class json_object:public value<json::Object,json::object>
	{
		json::object &get_object()	{return m_value;}
		json 	&operator[](const string &sz){return m_value[sz];}
	public:
		json_object(const json::object &obj):value(obj){}
		json_object(json::object &&obj)		:value(move(obj)){}

	};



	json::json(double value)				:m_ptr(make_shared<json_double>(value)){}
	json::json(int value)					:m_ptr(make_shared<json_int>(value)){}
	json::json(const char *value)			:m_ptr(make_shared<json_string>(value)){}
	json::json(const string &value)			:m_ptr(make_shared<json_string>(value)){}
	json::json(string &&value)				:m_ptr(make_shared<json_string>(move(value))){}
	json::json(const array &value)			:m_ptr(make_shared<json_array>(value)){}
	json::json(array &&value)				:m_ptr(make_shared<json_array>(move(value))){}
	json::json(const object &value)			:m_ptr(make_shared<json_object>(value)){}
	json::json(object &&value)				:m_ptr(make_shared<json_object>(move(value))){}



	const int 			&json::get_int()		const { return m_ptr->get_int();}
	const double 		&json::get_double()		const { return m_ptr->get_double();}
	const string 		&json::get_str()		const { return m_ptr->get_str();}
	const json::array	&json::get_array()		const { return m_ptr->get_array();}
	const json::object	&json::get_object()		const { return m_ptr->get_object();}

	json &json::operator[](int sz)				{ return const_cast<json &>(static_cast<const json&>(*this).operator[](sz)); }
	json &json::operator[](const string &sz)	{ return const_cast<json &>(static_cast<const json&>(*this).operator[](sz)); }
	json::array			&json::get_array()		{ return const_cast<json::array &>(static_cast<const json &>(*this).get_array()); }
	json::object		&json::get_object()		{ return const_cast<json::object &>(static_cast<const json &>(*this).get_object()); }

	void json::set_int(int value) 					{ m_ptr->get_int() = value; }
	void json::set_double(double value) 			{ m_ptr->get_double() = value; }
	void json::set_string(const string &value) 	{ m_ptr->get_str() = value; }

	const json &json::operator[](int sz)const
	{
		return (*m_ptr)[sz];
	}
	const json &json::operator[](const string & sz)const
	{
		return (*m_ptr)[sz];
	}

	json::Type json::type()const { return m_ptr->type();}
	string json::print() const
	{
		string out;
		print(out);
		return out;
	}
	void json::print(string &out)const
	{
		m_ptr->print(out);
	}


}

int main()
{
	json c=json(3);
	json d = json::array({c,c,c,c});
	assert(d.type()==json::Int);
	cout<<d.print()<<endl;

	json str=json("3.14");
	assert(str.type()==json::String);
	cout<<str.print()<<endl;

	json arr=json::array({3,4,5,6});//vector<json>({3,4,5,6})
	arr[0].set_int(1000);
	assert(arr.type()==json::Array);
	cout<<arr.print()<<endl;
	// assert(arr[0].type()==json::Int);
	assert(arr[0].type()==json::Int);

	json obj=json::object({
		{"k1",999},
		{"k2",json::array({1,2.3,"json.h"})},
		{"k3","hello world"}
	});

	obj["k1"] = 1000;
	assert(obj["k1"].type()==json::Int);
	assert(obj.type()==json::Object);
	cout<<obj.print()<<endl;

	json all=json::array({d,arr,obj});
	cout<<all.print()<<endl;
	return 0;
}

//熟悉友元的作用域 从父类接口调用到相同子类的接口
//父类受保护的成员在子类的public中覆盖对父类子类的影响

































